using System;
using System.Collections.Generic;
using System.Threading;

public class DelayDoAction
{
    private static DelayDoAction _Instance = new DelayDoAction();
    public static DelayDoAction Instance => _Instance;
    
    public class TimerAction
    {
        private volatile bool m_Canceled;
        private Action m_Action;
        private int m_DelayMiniSeconds;
        private long m_StartTicks;


        public bool canceled => m_Canceled;
        //public int delay => m_DelayMiniSeconds;
        
        /// <summary>
        /// 检查执行时间是否到了
        /// </summary>
        /// <param name="utcNow"></param>
        /// <returns></returns>
        public bool CheckTimeToRun(long utcNow)
        {
            return utcNow >= m_StartTicks + m_DelayMiniSeconds * 10000;
        }


        public TimerAction(Action action, int delayMiniSeconds)
        {
            m_StartTicks = DateTime.UtcNow.Ticks;
            
            m_Canceled = false;
            m_Action = action;
            m_DelayMiniSeconds = delayMiniSeconds;
        }

        public void Cancel()
        {
            m_Canceled = true;
        }

        public void Run()
        {
            m_Action();
        }
    }

    // 运行状态
    private volatile bool m_Running = false;
    
    private int m_Interval = 100;
    // 检测间隔 默认100ms
    public int Interval
    {
        get { return m_Interval; }
        set { m_Interval = value; }
    }

    private AtomLock m_Lock = new AtomLock();
    
    // 任务列表
    private List<TimerAction> m_Tasks = new List<TimerAction>();
    
    // 等待添加的任务列表
    private List<TimerAction> m_TasksWaitToAdd = new List<TimerAction>();
    
    public TimerAction Add(Action action, int miniSeconds)
    {
        if (action == null)
        {
            throw new Exception("ExTimer the action add can not be null");
        }

        if (miniSeconds <= 0)
        {
            throw new Exception($"ExTimer the miniSeconds {miniSeconds} <= 0");
        }

        // 添加任务
        TimerAction timerAction = new TimerAction(action, miniSeconds);
        
        m_Lock.DoAction(() =>
        {
            // 添加到列表
            m_TasksWaitToAdd.Add(timerAction);
            //Console.WriteLine($"Add {miniSeconds}");
            // 激活运行
            this.ActiveRunning();
        });
        
        return timerAction;
    }

    private void ActiveRunning()
    {
        if (m_Running) return;

        m_Running = true;
        Thread thread = new Thread(this.Update);
        thread.Start();
    }

    private void Update()
    {
        while (true)
        {
            // 添加任务
            if (m_TasksWaitToAdd.Count > 0)
            {
                m_Lock.DoAction(() =>
                {
                    m_Tasks.AddRange(m_TasksWaitToAdd);
                    m_TasksWaitToAdd.Clear();
                });
            }

            // 没有任务时，退出线程
            if (m_Tasks.Count == 0)
            {
                m_Running = false;
                break;
            }

            // 依次检测
            long utcNow = DateTime.UtcNow.Ticks;
            for (int i = 0; i < m_Tasks.Count;)
            {
                // 已取消
                if (m_Tasks[i].canceled)
                {
                    m_Tasks.RemoveAt(i);
                }
                // 时间到了
                else if (m_Tasks[i].CheckTimeToRun(utcNow))
                {
                    //Console.WriteLine($"{DateTime.Now} 执行{i}: {m_Tasks[i].delay}");
                    m_Tasks[i].Run();
                    m_Tasks.RemoveAt(i);
                    //Console.WriteLine($"剩余{i}: {m_Tasks.Count}");
                }
                // 时间未到，继续等待
                else
                {
                    ++i;
                }
            }

            // 等待一定时间
            // Console.WriteLine("running");
            Thread.Sleep(m_Interval);
        }
    }
}